package graph;

import static ogl.vecmathimp.FactoryDefault.vecmath;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glViewport;
import static org.lwjgl.opengl.GL20.glUseProgram;

import java.nio.FloatBuffer;

import javax.swing.text.View;

import graph.scenes.DefaultScene;
import graph.scenes.Scene;
import graph.scenes.iPadScene;
import ogl.app.App;
import ogl.app.Input;
import ogl.app.OpenGLApp;
import ogl.vecmath.Matrix;
import ogl.vecmath.Vector;
import ogl.vecmathimp.MatrixImp;

import org.lwjgl.opengl.GL11;

import shader.Shader;

public class Main implements App {
	private static DefaultScene scene;
	private static Matrix viewMatrix;
	private static Matrix projectionMatrix;
	private boolean first = true;
	private static float time = 0f;

	static public void main(String[] args) {
		new OpenGLApp("Rotating Cube - OpenGL ES 2.0 (lwjgl)", new Main())
				.start();
		// OpenGL App ruft init() auf, dann simulate(), dann display(),
		// simulate(), display() etc.
	}

	@Override
	public void init() {
		scene = new DefaultScene();
		scene.buildSceneGraph();

		// Set background color
		glClearColor(0.9f, 0.9f, 1f, 1.0f);

		// Enable depth testing.
		glEnable(GL11.GL_DEPTH_TEST);
		
		glEnable(GL11.GL_LIGHTING);
		glEnable(GL11.GL_LIGHT0);
	}
	
	@Override
	public void simulate(float elapsed, Input input) {
		scene.simulateAllEntities(elapsed, input);
		time = elapsed;
	}

	@Override
	public void display(int width, int height) {
		// Adjust the the viewport to the actual window size. This makes the
		// rendered image fill the entire window.
		glViewport(0, 0, width, height);

		// Clear all buffers.
		glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

		// Assemble the transformation matrix that will be applied to all
		// vertices in the vertex shader.
		float aspect = (float) width / (float) height;

		// The perspective projection. Camera space to NDC.
		projectionMatrix = vecmath.perspectiveMatrix(60f, aspect, 0.1f, 100f);
		
		/* Camera */
		// The inverse camera transformation. World space to camera space.
		viewMatrix = scene.findCamera();
		
		/* Bind the shader the first time */
		if (first) {
			Shader sceneDefShader = scene.getDefaultShader();
			int program = sceneDefShader.getProgram();
			glUseProgram(program);
			sceneDefShader.setProjectionMatrixUniform(projectionMatrix);
			sceneDefShader.setViewMatrixUniform(viewMatrix);
			first = false;
		}
	
		/* Skybox */
		scene.drawSkybox((MatrixImp) viewMatrix.getRotation());
		
		/* Scene */
		scene.draw((MatrixImp) MatrixImp.identity);
	}

	public static Scene getScene() {
		return scene;
	}

	public static Matrix getViewMatrix() {
		return viewMatrix;
	}

	public static Matrix getProjectionMatrix() {
		return projectionMatrix;
	}
	
	public static float getElapsed() {
		return time;
	}

	// modelMatrix = für jedes Objekt
	// projectionMatrix = immer gleich, hängt nur von Fenstergröße ab
	// viewMatrix = Kamera

	// Licht finden lassen und dann in den Shadern setzen (wie die im Shader
	// benutzt werden -> vlg Folien/Google etc, momentan noch nicht drin)

}
